package com.michaellou.Test;

//package com.yihaodian.indexproxy.dao;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.Map.Entry;

public class TimeLocalCache {
	
	private static final long MOST_LIVE_TIME = 3600;
	
	private static final Object lock = new String("the sync lock");
	
	private static Triger triger = new Triger();
	
	private static Map<String, Object> cache = new HashMap<String, Object>();
	
	/**
	 * cache a object with a key, and live for the specified seconds
	 * 
	 * @param key
	 * @param obj
	 * @param seconds at most to 3600(an hour)
	 */
	public static void put(String key, Object obj, long seconds){
		synchronized(lock){
			final long realSeconds = seconds < MOST_LIVE_TIME? seconds: MOST_LIVE_TIME;
			long deadline = System.currentTimeMillis() + (realSeconds << 10);
			cache.put(key, obj);
			triger.addTriger(key, deadline);
		}
	}
	
	/**
	 * 
	 * @param key
	 * @return
	 * @deprecated not sync with get() method, so it's danger
	 */
	@Deprecated
	public static boolean cached(String key){
		return cache.containsKey(key);
	}
	
	public static Object get(String key){
		return cache.get(key);
	}
	
	static{
		new Thread(){
			@Override
			public void run(){
				while(true){
					synchronized (lock) {
						Set<String> keys = triger.check();
						System.out.println(triger.toString()+"keys:"+keys.toString());
						if(! keys.isEmpty()){
							for(String key: keys){
								cache.remove(key);
							}
						}
					}
					try {
						sleep(499);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			}
		}.start();
	}
}

class Triger{
	
	private TreeMap<Long, Set<String>> timeMap = new TreeMap<Long, Set<String>>();
	
	public void addTriger(String key, Long deadline){
		Set<String> keys = timeMap.get(deadline);
		if(keys == null){
			keys = new HashSet<String>();
		}
		keys.add(key);
		timeMap.put(deadline, keys);
	}
	
	public Set<String> check(){
		Long current = System.currentTimeMillis();
		Map<Long, Set<String>> toKill = timeMap.headMap(current);
		Set<String> ret = new HashSet<String>();
		List<Long> keysRemove = new ArrayList<Long>();
		for(Entry<Long, Set<String>> entry: toKill.entrySet()){
			ret.addAll(entry.getValue());
			keysRemove.add(entry.getKey());
		}
		for(Long key: keysRemove){
			timeMap.remove(key);
		}
		return ret;
	}
	
}
